package org.simplextensions.ui.menu;

import org.simplextensions.di.DependencyInjector;
import org.simplextensions.di.annotations.Point;
import org.simplextensions.di.annotations.Registry;
import org.simplextensions.registry.IExtensionRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public abstract class MenuManager {

	private static final Logger log = LoggerFactory.getLogger(MenuManager.class);

	@Registry
	private IExtensionRegistry extensionRegistry;

	@Point
	private MenuExtensionPoint mep;

	public MenuManager(IExtensionRegistry extensionRegistry) {
		DependencyInjector.resolveDependency(extensionRegistry, this);
	}

	protected JMenu createMenu(MenuExtensionMetadata memd) {
		if (memd.getType() == MenuExtensionType.Menu) {
			try {
				JMenu subMenu = new JMenu();
				subMenu.setText(memd.getExecutable().getLabel(memd));

				for (MenuExtensionMetadata submemd : memd.getSubItems()) {
					if (submemd.getType() == MenuExtensionType.Menu) {
						JMenu createdSubMenu = createMenu(submemd);
						subMenu.add(createdSubMenu);
					} else if (submemd.getType() == MenuExtensionType.Separator) {
						subMenu.addSeparator();
					} else if (submemd.getType() == MenuExtensionType.Action) {
						JMenuItem item = createAction(submemd, subMenu);
						if (item != null)
							subMenu.add(item);
						else
							log.debug("cannot handle action interface: " + memd.getId());
					}
				}
				return subMenu;
			} catch (Exception e) {
				log.error("", e);
			}
		} else {
			log.warn(memd.getType().name() + " not supported in MenuBar (" + memd.toString() + ")");
		}
		return null;
	}

	protected JMenuItem createAction(MenuExtensionMetadata submemd, JMenu parentMenu) {
		JMenuItem result = null;
		if (submemd.getType() == MenuExtensionType.Action) {

			IMenuExtension executable = submemd.getExecutable();
			if (executable instanceof IActions) {
				result = createMenuItems(submemd, parentMenu, (IActions) executable);
			} else if (executable instanceof IAction) {
				result = createMenuItem(submemd, (IAction) executable);
			}
		}
		return result;
	}

	protected JMenuItem createMenuItems(final MenuExtensionMetadata submemd, final JMenu parentMenu, final IActions executable) {
		JMenuItem result;
		final JMenu menu = new JMenu();
		parentMenu.addMenuListener(new MenuListener() {
			public void menuSelected(MenuEvent e) {
				menu.removeAll();
				fillMenu(submemd, executable, menu);
			}

			public void menuCanceled(MenuEvent e) {
			}

			public void menuDeselected(MenuEvent e) {
			}
		});
		menu.setText(executable.getLabel(submemd));
		result = menu;
		return result;
	}

	protected JMenuItem createMenuItem(final MenuExtensionMetadata submemd, final IAction executable) {
		JMenuItem result = new JMenuItem();
		result.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				executable.run(submemd);
			}
		});
		result.setEnabled(executable.isEnabled(submemd));
		result.setText(executable.getLabel(submemd));

		return result;
	}

	public void fillMenu(MenuExtensionMetadata submemd, IActions executable, JMenu menu) {
		IAction[] actions = executable.getActions();
		for (IAction action : actions) {
			JMenuItem menuItem = createMenuItem(submemd, action);

			if (menuItem != null)
				menu.add(menuItem);
		}
	}

	protected IExtensionRegistry getExtensionRegistry() {
		return extensionRegistry;
	}

	protected MenuExtensionPoint getMep() {
		return mep;
	}

}
